/**
 * 
 */
package org.jinion.database.model;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jinion.exception.JinionRuntimeException;



/**
 * Every operation of AbstractDatabase will return an instance of this class.<br>
 * It is the abstract object wrapping database execution result including <br>
 * generated keys, affected rows and returned table columns and rows.
 * 
 * @author zhlmmc
 *
 */
public abstract class AbstractResult {
	private static final Log log = LogFactory.getLog(AbstractResult.class);
	
	protected int affectedRows;
	protected AbstractTable table;
	protected LinkedList<Integer> generatedKeys;
	
	public AbstractResult(int affectedRows, ResultSet generatedKeys, ResultSet resultSet) throws SQLException{
		if (affectedRows > 0) {
			this.affectedRows = affectedRows;
		}
		else{
			this.affectedRows = 0;
		}
		
		if (generatedKeys != null) {
			this.generatedKeys = new LinkedList<Integer>();
			while (generatedKeys.next()) {
				this.generatedKeys.add(generatedKeys.getInt(1));
			}
		}
		else{
			this.generatedKeys = null;
		}
		
		if (resultSet != null) {
			this.table = buildTable(resultSet);
		}
		else{
			table = null;
		}
	}
	
	protected abstract AbstractTable buildTable(ResultSet resultSet);
	
	/**
	 * The same value as "table.getRows().size()".
	 * @return the number of rows returned
	 */
	public int size(){
		return this.table.getRows().size();
	}

	/**
	 * Get the number of affected rows of the operation.
	 * @return
	 */
	public int getAffectedRows() {
		return affectedRows;
	}

	/**
	 * Data returned by query operation will be filled in an instance of AbstractTable.<br>
	 * This method returns the table.
	 * @return
	 */
	public AbstractTable getTable() {
		return table;
	}
	
	/**
	 * index starts from 0, 1...
	 * @param index
	 * @return
	 */
	public Object getGeneratedKey(int index){
		if (this.generatedKeys == null) {
			return null;
		}
		else if (index < 0 || index >= generatedKeys.size()) {
			JinionRuntimeException jre = new JinionRuntimeException("Generated key index ? is out of bound.", index);
			log.error(jre);
			throw jre;
		}
		else{
			return this.generatedKeys.get(index);
		}
	}

	/**
	 * For convenient, this method return the first generated key. 
	 * @return
	 */
	public Object getFirstGeneratedKey(){
		if (this.generatedKeys == null || this.generatedKeys.size() == 0) {
			return null;
		}
		
		return generatedKeys.get(0);
	}

	public LinkedList<Integer> getGeneratedKeys() {
		return generatedKeys;
	}
	
}
